﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Threading;
using System.Xml.Serialization;
using Mvvm;


namespace LayoutPlanning.Model
{
    [Serializable]
    public class ObservableDragableObject : BindableBase
    {
        private double _angle;
        private Point _origo = new Point();

        [NonSerialized] private TranslateTransform _origoTranslateTransformation = new TranslateTransform();

        private Point _position = new Point();

        [NonSerialized] protected RotateTransform _rotate = new RotateTransform(0);

        [NonSerialized] protected TransformGroup _transform;

        [NonSerialized] protected TranslateTransform _translateTransform = new TranslateTransform();
        // new TranslateTransform();
        [NonSerialized]
        private bool internalchange;

        public ObservableDragableObject()
        {
            InitTransforms();
            
        }

        public void InitTransforms()
        {
            if(_rotate == null)
                _rotate = new RotateTransform(_angle);
            if (_translateTransform == null)
                _translateTransform = new TranslateTransform(_position?.X??0, _position?.Y??0);
            _transform = new TransformGroup()
            {
                Children = new TransformCollection(new List<Transform>()) {_rotate, _translateTransform}
            };
            RaisePropertiesChanged(nameof(Transform));
            RaisePropertiesChanged(nameof(Position));
            if (_origoTranslateTransformation == null)
            {
                _origoTranslateTransformation = new TranslateTransform(Origo.X, Origo.Y);
                RaisePropertiesChanged(nameof(Origo));
            }
            _position.PropertyChanged += (o, args) =>
            {
                if (!internalchange)
                {
                    _translateTransform.Y = Position.Y + Origo.Y;
                    _translateTransform.X = Position.X + Origo.X;
                }
            };
            Origo.PropertyChanged += Origo_PropertyChanged;
            _origoTranslateTransformation.Changed += _origoTranslateTransformation_Changed;
        }

        public Point Position
        {
            get { return _position; }
            set
            {
                _position.X = value.X;
                _position.Y = value.Y;
                _position.Z = value.Z;


                //RefreshPos();
            }
        }

        public Point Origo
        {
            get { return _origo; }
            set
            {
                if (Origo == value)
                    return;
                _origo = value;
                RaisePropertyChanged();
                if (_translateTransform != null)
                {
                    internalchange = true;
                    Position.Y = _translateTransform.Y - Origo.Y;

                    Position.X = _translateTransform.X - Origo.X;
                    internalchange = false;
                }
                Origo.PropertyChanged += Origo_PropertyChanged;
                _origoTranslateTransformation.Changed += _origoTranslateTransformation_Changed;
            }
        }

        [XmlIgnore]
        public TranslateTransform OrigoTransformation => _origoTranslateTransformation;

        public double Angle
        {
            get
            {
                if(_rotate == null)
                    InitTransforms();
                return _rotate.Dispatcher.Invoke(() => _rotate.Angle);
            }
            set
            {
                var a = value%360;
                while (a < 0)
                    a += 360;
                while (a > 360)
                    a -= 360;
                _rotate.Angle = a;
                _angle = a;
                RaisePropertyChanged();
            }
        }

        [XmlIgnore]
        public TransformGroup Transform => _transform;

        private void Origo_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (Origo.X == _origoTranslateTransformation.X && Origo.Y == _origoTranslateTransformation.Y)
                return;

            _origoTranslateTransformation.X = Origo.X;
            _origoTranslateTransformation.Y = Origo.Y;


            Position.Y = _translateTransform.Y - Origo.Y;
            Position.X = _translateTransform.X - Origo.X;
        }

        private void _origoTranslateTransformation_Changed(object sender, EventArgs e)
        {
            if (Origo.X == _origoTranslateTransformation.X && Origo.Y == _origoTranslateTransformation.Y)
                return;
            Origo.X = _origoTranslateTransformation.X;
            Origo.Y = _origoTranslateTransformation.Y;
        }
    }
}